package com.yanqu.road.server.gameplayer.module.activity.greattrade;

import com.yanqu.road.dao.impl.activity.greattrade.UserGreatTradeDataDaoImpl;
import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.args.ValueFourParamArgs;
import com.yanqu.road.entity.activity.greattrade.*;
import com.yanqu.road.entity.activity.greattrade.config.*;
import com.yanqu.road.entity.activity.greattrade.enums.eGreatTradeAttrs;
import com.yanqu.road.entity.config.goods.MallInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.*;
import com.yanqu.road.entity.player.UserBeauty;
import com.yanqu.road.pb.activity.GreatTradeProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.ActivityMallModule;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.BeautyModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.ServerLanguageMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.activity.greattrade.GreatTradeConfig;
import com.yanqu.road.server.manger.activity.greattrade.GreatTradeMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.pb.GreatTradeActivityPb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

public class GreatTradeModule extends GeneralModule {

    UserGreatTradeData userData;

    Random random = new Random();

    public GreatTradeModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        ActivityInfo activityInfo = GreatTradeMgr.getActivityInfo();
        if(ActivityMgr.activityInShowTime(activityInfo)) {
            userData = new UserGreatTradeDataDaoImpl().getUserGreatTradeData(activityInfo.getActivityId(), player.getUserId());
        }
        return false;
    }

    @Override
    public boolean afterLoadData() {
        return false;
    }

    @Override
    public boolean saveData() {
        if(userData != null){
            if(userData.isInsertOption()){
                new UserGreatTradeDataDaoImpl().add(userData);
            }else if(userData.isUpdateOption()){
                new UserGreatTradeDataDaoImpl().update(userData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {

        if (!SystemOpenMgr.systemOpen(player, eSystemId.GreatTradeActivity.getValue())) {
            return;
        }

        syncConfig();

        if(!resetOneDay()) {
            syncUserData();
        }

    }

    public void syncUserData() {

        GreatTradeConfig config = GreatTradeMgr.getConfig();
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }

        if(SystemOpenMgr.systemOpen(player, eSystemId.GreatTradeActivity.getValue())){
            if(userData == null){
                initUserData();
            }
        }

        if(userData == null){
            return;
        }
        GreatTradeProto.GreatTradeUserDataSync.Builder syncMsg = GreatTradeProto.GreatTradeUserDataSync.newBuilder();
        GreatTradeProto.GreatTradeUserDataTemp.Builder builder = GreatTradeActivityPb.buildUserTemp(userData, config);
        syncMsg.setUserData(builder);
        player.sendPacket(Protocol.U_GREAT_TRADE_SYNC_DATA, syncMsg);

    }

    public void syncConfig() {

        GreatTradeConfig config = GreatTradeMgr.getConfig();
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }


        GreatTradeProto.GreatTradeConfigDataSync.Builder configSync = GreatTradeProto.GreatTradeConfigDataSync.newBuilder();
        GreatTradeProto.GreatTradeConfigTemp.Builder configTemp = GreatTradeProto.GreatTradeConfigTemp.newBuilder();
        for (GreatTradeEventInfo eventInfo : config.getEventInfoList()) {
            GreatTradeProto.GreatTradeEventTemp.Builder builder = GreatTradeActivityPb.buildEventTemp(eventInfo, player.getLanguage());
            configTemp.addEvent(builder);
        }

        for (GreatTradeGoodsInfo goodsInfo : config.getGoodsInfoList()) {
            GreatTradeProto.GreatTradeGoodsTemp.Builder builder = GreatTradeActivityPb.buildGoodsTemp(goodsInfo);
            configTemp.addGoods(builder);
        }

        for (GreatTradeTitleInfo titleInfo : config.getTitleInfoList()) {
            GreatTradeProto.GreatTradeTitleTemp.Builder builder = GreatTradeActivityPb.buildTitleTemp(titleInfo);
            configTemp.addTitle(builder);
        }

        for (GreatTradeSkillsInfo skillsInfo : config.getSkillsInfoList()) {
            GreatTradeProto.GreatTradeSkillsTemp.Builder builder = GreatTradeActivityPb.buildSkillsTemp(skillsInfo, player.getLanguage());
            configTemp.addSkill(builder);
        }

        for (GreatTradeUnlockSkillInfo skillInfo : config.getUnlockSkillInfoList()) {
            GreatTradeProto.GreatTradeSkillsUnlockTemp.Builder builder = GreatTradeProto.GreatTradeSkillsUnlockTemp.newBuilder();
            builder.setId(skillInfo.getId());
            builder.setTitle(ServerLanguageMgr.getContent(skillInfo.getTitle(), player.getLanguage()));
            builder.setDesc(ServerLanguageMgr.getContent(skillInfo.getDesc(), player.getLanguage()));
            builder.addAllParams(skillInfo.getParams());
            configTemp.addUnlock(builder);
        }

        configSync.setConfig(configTemp);

        player.sendPacket(Protocol.U_GREAT_TRADE_SYNC_CONFIG, configSync);
    }

    /**
     * 初始化玩家数据
     */
    public synchronized void initUserData() {
        // 系统未解锁
        if (!SystemOpenMgr.systemOpen(player, eSystemId.GreatTradeActivity.getValue())) {
            return;
        }

        // 没有活动
        if (!ActivityMgr.activityInShowTime(GreatTradeMgr.getActivityInfo()) || GreatTradeMgr.getConfig() == null) {
            return;
        }

        ActivityInfo activityInfo = GreatTradeMgr.getActivityInfo();

        // 已经有数据了
        if (userData != null && userData.getActivityId() == activityInfo.getActivityId()) {
            return;
        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        UserGreatTradeData tmpUserData = new UserGreatTradeData();
        tmpUserData.setActivityId(activityInfo.getActivityId());
        tmpUserData.setUserId(player.getUserId());
        tmpUserData.setDayFreeTimes(config.getFreeNum());
        tmpUserData.setMaxAssets("0");
        tmpUserData.setBeautyMap(new HashMap<>());
        tmpUserData.setEventMap(new HashMap<>());
        GreatTradeMgr.initTradeData(tmpUserData);
        tmpUserData.setDayResetTime(DateHelper.getTodayZeroTime());
        tmpUserData.setInsertOption();
        userData = tmpUserData;

    }

    /**
     * 检查是否开启商途
     */
    private int checkOpen() {
        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        if(userData.getTradeStatus().isTradeFinish()){
            return GameErrorCode.E_GREAT_TRADE_HAD_CLOSE;
        }
        return 0;
    }

    /**
     * 开启商途
     */
    public int openTrade() {
        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        //上次商途是否结束
        if(!userData.getTradeStatus().isTradeFinish()){
            return GameErrorCode.E_GREAT_TRADE_HAD_OPEN;
        }

        //免费次数是否足够
        boolean free = userData.getDayFreeTimes() > 0;

        //道具是否足够
        Property consume = PropertyHelper.parseStringToProperty(config.getOpenItemId() + "=" + config.getOpenItemNum());
        if(!free){
            boolean enough = player.getModule(CurrencyModule.class).currencyIsEnough(consume);
           if(!enough){
               return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
           }
        }

        //初始商途数据
        GreatTradeSimpleStatus tradeStatus = GreatTradeMgr.initTradeBaseData(userData, config, random);
        initAllEvent(userData, config);
        if(!free){
            tradeStatus.setUseGoods(true);
        }

        //出生进程
        List<Integer> paramList = new ArrayList<>();
        paramList.add(tradeStatus.getBirth());
        addMilepostRecord(1, tradeStatus.getAge(), paramList);
        addMilepostRecord(2, tradeStatus.getAge(), paramList);

        //行商市场价格
        Map<Integer, Integer> goodsPriceMap = GreatTradeMgr.initYearMarketGoodsPrice(userData, tradeStatus, config, random);

        //事件触发
        //随机事件
        //int randomEventId = GreatTradeMgr.calYearRandomEvent(tradeStatus, config, random);
        //tradeStatus.setRandomEventId(randomEventId);
        //GreatTradeMgr.completeRandomEvent(player, userData, userData.getTradeStatus());

        //初始成功，设置值，避免数据脏了
        userData.setTradeStatus(tradeStatus);
        userData.setGoodsPriceList(goodsPriceMap);

        userData.setDayTradeTimes(1 + userData.getDayTradeTimes());
        userData.setTotalTradeTimes(1 + userData.getTotalTradeTimes());
        //扣减免费次数
        if(free){
            userData.setDayFreeTimes(userData.getDayFreeTimes() - 1);
        }else {
            player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.GreatTradeActivity, eLogMoneyType.GreatTradeActivityOpenTradeConsume);
        }

        calPrestige(userData.getTradeStatus(), config, true);
        userData.setUpdateOption();

        GreatTradeProto.GreatTradeOpenRespMsg.Builder respMsg = GreatTradeProto.GreatTradeOpenRespMsg.newBuilder().setRet(0);
        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_OPEN, respMsg);
        return 0;
    }

    /**
     * 行商购买
     */
    public int buyGoods(int id, int num) {
        int ret = checkOpen();
        if (ret != 0) return ret;

//        if(userData.getTradeStatus().isIll()){
//            return GameErrorCode.E_GREAT_TRADE_CURR_YEAR_ILL;
//        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        GreatTradeGoodsInfo goodsInfo = config.getGreatTradeGoodsInfo(id);
        //商品是否存在
        if(goodsInfo == null){
            return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
        }
        //市场是否可以买
        Map<Integer, Integer> priceMap = userData.getGoodsPriceList();
        if(!priceMap.containsKey(id)){
            return GameErrorCode.E_GREAT_TRADE_NO_IN_MARKET;
        }

        long price = priceMap.get(id);
        //购买消耗现银
        BigInteger cost = BigInteger.valueOf(price).multiply(BigInteger.valueOf(num));
        BigInteger sliver = new BigInteger(userData.getTradeStatus().getSilver());
        if(sliver.compareTo(cost) < 0) {
            return GameErrorCode.E_GREAT_TRADE_SLIVER_NO_ENOUGH;
        }

        //仓储容量是否足够
        int count = GreatTradeMgr.getBagGoodsCount(userData);
        if(count + num > GreatTradeMgr.getUserBagCap(userData, config)){
            return GameErrorCode.E_GREAT_TRADE_CAPACITY_NO_ENOUGH;
        }

        addBagGoods(id, num, cost);
        GreatTradeSimpleStatus tradeStatus = userData.getTradeStatus();
        tradeStatus.setSilver(sliver.subtract(cost).toString());

        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);
        userData.setUpdateOption();

        GreatTradeProto.GreatTradeGoodsBuyRespMsg.Builder respMsg = GreatTradeProto.GreatTradeGoodsBuyRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUser(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_BUY_GOODS, respMsg);

        //日志
        AutoLogMgr.add(new LogGreatTradeGoods(player.getUserId(), config.getActivityId(), id, 1, num, "", userData.getTradeStatus().getSilver(),
            GreatTradeMgr.getBagGoodsCount(userData), userData.getTradeStatus().getHealth(), userData.getTradeStatus().getPrestige(), userData.getTradeStatus().getTitle(),
                userData.getTradeStatus().getAge(), userData.getTradeStatus().getAssets(), userData.getTotalTradeTimes()));

        return 0;
    }

    private void addBagGoods(int id, int num, BigInteger cost) {
        GreatTradeGoods goods = GreatTradeMgr.getBagGoods(userData, id);
        if(goods == null){
            goods = new GreatTradeGoods();
            goods.setId(id);
            goods.setNum(num);
            goods.setPrice(cost.toString());
            userData.getGoodsList().add(goods);
        }else {
            goods.setPrice(new BigInteger(goods.getPrice()).add(cost).toString());
            goods.setNum(goods.getNum() + num);
        }
    }

    /**
     * 行商出售
     */
    public int soldGoods(int id, int num) {
        int ret = checkOpen();
        if (ret != 0) return ret;

//        if(userData.getTradeStatus().isIll()){
//            return GameErrorCode.E_GREAT_TRADE_CURR_YEAR_ILL;
//        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        GreatTradeGoodsInfo goodsInfo = config.getGreatTradeGoodsInfo(id);
        //商品是否存在
        if(goodsInfo == null){
            return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
        }
        //背包是否有该商品
        GreatTradeGoods goods = GreatTradeMgr.getBagGoods(userData, id);
        if(goods == null){
            return GameErrorCode.E_GREAT_TRADE_GOODS_NO_ENOUGH;
        }
        if(goods.getNum() < num){
            return GameErrorCode.E_GREAT_TRADE_GOODS_NO_ENOUGH;
        }
        BigInteger reducePrice;
        if(num == goods.getNum()){
            reducePrice = new BigInteger(goods.getPrice());
        } else {
            reducePrice = new BigDecimal(goods.getPrice()).multiply(BigDecimal.valueOf(num)).divide(BigDecimal.valueOf(goods.getNum()), 0, BigDecimal.ROUND_DOWN).toBigInteger();
        }

        //市场是否有该商品
        Map<Integer, Integer> priceMap = userData.getGoodsPriceList();
        if(!priceMap.containsKey(id)){
            return GameErrorCode.E_GREAT_TRADE_NO_IN_MARKET;
        }

        BigInteger sellSliver = BigInteger.valueOf(priceMap.get(id)).multiply(BigInteger.valueOf(num));
        int addition = 0;
        //盈利部分
        BigInteger addSliver = sellSliver.subtract(reducePrice);
        if(addSliver.compareTo(BigInteger.ZERO) > 0){
            //出售buff，针对盈利部分
            addition = getSellAddition(id, userData.getBeautyMap(), random, config);
            if (addition > 0) {
                sellSliver = sellSliver.add(new BigDecimal(addSliver).multiply(BigDecimal.valueOf(addition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).toBigInteger());
            }
        }
        //大涨价格变界是平价最大值
        List<String> changeList = StringUtils.stringToStringList(goodsInfo.getChangeParam(), "\\|");
        List<Integer> changeList1 = StringUtils.stringToIntegerList(changeList.get(1), ";");
        int limitPrice = new BigDecimal(goodsInfo.getBasePrice()).multiply(BigDecimal.valueOf(changeList1.get(1))).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).intValue();
        //商品是否大涨，平价最大值
        if(priceMap.get(id) > limitPrice){
            userData.getTradeStatus().setSellSurgeTimes(1 + userData.getTradeStatus().getSellSurgeTimes());
            checkSkillUnlock("11", "0", "" + userData.getTradeStatus().getSellSurgeTimes(), config);
        }


        userData.getTradeStatus().addSellMoney(id, sellSliver);
        userData.getTradeStatus().setGooodsAddSum(new BigInteger(userData.getTradeStatus().getGooodsAddSum()).add(sellSliver.subtract(reducePrice)).toString());

        goods.setNum(goods.getNum() - num);
        goods.setPrice(new BigInteger(goods.getPrice()).subtract(reducePrice).toString());
        userData.getTradeStatus().setSilver(sellSliver.add(new BigInteger(userData.getTradeStatus().getSilver())).toString());
        userData.getTradeStatus().setSellTimes(1 + userData.getTradeStatus().getSellTimes());

        //健康点流失
        if(userData.getTradeStatus().getSellTimes() % config.getHealthyLoseSell().get(0) == 0){
            consumeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(eGreatTradeAttrs.Health.getId() + "=" + config.getHealthyLoseSell().get(1)), config);
        }

        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);
        //累计行商收益
        BigInteger goodsProfit = new BigInteger(userData.getTradeStatus().getGoodsProfit());
        userData.getTradeStatus().setGoodsProfit(goodsProfit.add(sellSliver.subtract(reducePrice)).toString());

        userData.setUpdateOption();

        Property reward = checkTitleInfoChange(userData.getTradeStatus().getTitle(), userData.getTradeStatus(), config);
        if(reward != null) {
            changeTradeResource(userData.getTradeStatus(), reward, config);
            addTitleChangeMilepostRecord(userData, userData.getTradeStatus().getTitle(), 1, 0, 0);
            syncTitleChange(userData.getTradeStatus(), PropertyHelper.parsePropertyToString(reward));
            calPrestige(userData.getTradeStatus(), config, true);
            checkSkillUnlock("4", "" + userData.getTradeStatus().getTitle(), "1", config);
            userData.setUpdateOption();
        }

        GreatTradeProto.GreatTradeGoodsBuyRespMsg.Builder respMsg = GreatTradeProto.GreatTradeGoodsBuyRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setAddition(addition);
        respMsg.setUser(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_SOLD_GOODS, respMsg);

        //行商销售额过千万
        BigInteger sum = BigInteger.ZERO;
        for (Map.Entry<Integer, String> longEntry : userData.getTradeStatus().getSellMoney().entrySet()) {
            sum = sum.add(new BigInteger(longEntry.getValue()));
        }
        if(sum.compareTo(BigInteger.valueOf(10000000L)) >= 0){
            player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(BigInteger.ONE, 8));
        }

        //日志
        AutoLogMgr.add(new LogGreatTradeGoods(player.getUserId(), config.getActivityId(), id, 0, num, sellSliver.subtract(reducePrice).toString(), userData.getTradeStatus().getSilver(),
                GreatTradeMgr.getBagGoodsCount(userData), userData.getTradeStatus().getHealth(), userData.getTradeStatus().getPrestige(), userData.getTradeStatus().getTitle(),
                userData.getTradeStatus().getAge(), userData.getTradeStatus().getAssets(), userData.getTotalTradeTimes()));
        return 0;
    }

    private int getSellAddition(int id, Map<Integer, GreatTradeBeautySkill> beautyMap, Random random, GreatTradeConfig config) {
        int addition = 0;

        addition += GreatTradeMgr.getSkillAddition(5, beautyMap, id, random, config);

        addition += GreatTradeMgr.getSkillAddition(6, beautyMap, id, random, config);

        addition += GreatTradeMgr.getSkillAddition(7, beautyMap, id, random, config);

        return addition;
    }

    /**
     * @param type 1:行商；2：外出；3：产业；4：盐场；5：随机事件
     */
    private void addTitleChangeMilepostRecord(UserGreatTradeData userData, int title, int type, int areaId, int eventId) {
        List<Integer> paramList = new ArrayList<>();
        paramList.add(title);
        if(type == 1){
            paramList.add(type);
            int id = 0;
            BigInteger maz = BigInteger.ZERO;
            for (GreatTradeGoods goods : userData.getGoodsList()) {
                BigInteger price = new BigInteger(goods.getPrice());
                if(price.compareTo(maz) > 0){
                    id = goods.getId();
                    maz = price;
                }
            }
            paramList.add(id);
        }else if(type == 2){
            paramList.add(type);
            paramList.add(eventId);
            paramList.add(areaId);
        }else if(type == 5){
            paramList.add(type);
            paramList.add(eventId);
        }
        addMilepostRecord(3, userData.getTradeStatus().getAge(), paramList);
    }

    /**
     * 商途进程
     */
    private void addMilepostRecord(int type, int age, List<Integer> paramList) {
        //产业、盐场首次购买  首次淘宝
        if(type == 4 || type == 6 || type == 5){
            for (GreatTradeMilepostRecord record : userData.getMilepostRecordList()) {
                if(record.getType() == type){
                    return;
                }
            }
        }
        //称号变化
        if(type == 3){
            for (GreatTradeMilepostRecord record : userData.getMilepostRecordList()) {
                List<Integer> list = StringUtils.stringToIntegerList(record.getParams(), "\\|");
                if(paramList.get(0).equals(list.get(0)) && record.getType() == type){
                    return;
                }
            }
        }
        GreatTradeMilepostRecord record = new GreatTradeMilepostRecord(type, age, StringUtils.listToString(paramList, "|"));
        userData.getMilepostRecordList().add(record);
        userData.setUpdateOption();
    }

    /**
     * 购买产业
     */
    public int buyIndustry(int id, int num) {
        int ret = checkOpen();
        if (ret != 0) return ret;

//        if(userData.getTradeStatus().isIll()){
//            return GameErrorCode.E_GREAT_TRADE_CURR_YEAR_ILL;
//        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        GreatTradeGoodsInfo goodsInfo = config.getGreatTradeGoodsInfo(id);
        if(goodsInfo == null){
            return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
        }

        if (!isUnLockTypeByTitle(config, 3)) return GameErrorCode.E_GREAT_TRADE_INDUSTRY_LOCK;

        if(userData.getIndustry().getId() > 0 && userData.getIndustry().getId() != id){
            return GameErrorCode.E_GREAT_TRADE_CAN_NOT_BY_INDUSTRY;
        }

        //首次购买份额
        if(userData.getIndustry().getId() == 0 && num < 1000){
            return GameErrorCode.E_GREAT_TRADE_CAN_NOT_BY_INDUSTRY;
        }

        List<Integer> exParamList = StringUtils.stringToIntegerList(goodsInfo.getExParam(), "\\|");
        if(exParamList.size() == 6 && exParamList.get(5) > 0){
            if(userData.getIndustry().getShares() + num > exParamList.get(5)){
                return 8606;//暂时
            }
        }

        //现银扣除
        BigInteger cost = new BigInteger(goodsInfo.getBasePrice()).multiply(BigInteger.valueOf(num));
        BigInteger sliver = new BigInteger(userData.getTradeStatus().getSilver());
        if(sliver.compareTo(cost) < 0){
            return GameErrorCode.E_GREAT_TRADE_SLIVER_NO_ENOUGH;
        }

        GreatTradeIndustry industry = userData.getIndustry();
        if(industry.getId() == 0){
            industry.setId(id);
            industry.setStartYear(userData.getTradeStatus().getCurYear());
            industry.setPrice(Long.valueOf(goodsInfo.getBasePrice()));
        }

        industry.setShares(industry.getShares() + num);

        userData.getTradeStatus().setSilver(sliver.subtract(cost).toString());

        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);

        //进程
        List<Integer> paramList = new ArrayList<>();
        paramList.add(industry.getId());
        addMilepostRecord(4, userData.getTradeStatus().getAge(), paramList);
        userData.setUpdateOption();

        GreatTradeProto.GreatTradeIndustryBuyRespMsg.Builder respMsg = GreatTradeProto.GreatTradeIndustryBuyRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_INDUSTRY_BUY, respMsg);

        //日志
        AutoLogMgr.add(new LogGreatTradeIndustry(player.getUserId(), config.getActivityId(), id,
            1, num, cost.toString(), userData.getTotalTradeTimes()));

        return 0;
    }

    private boolean isUnLockTypeByTitle(GreatTradeConfig config, int type) {
        List<Integer> unLockList = config.getUnLockType(userData.getTradeStatus().getTitle());
        return unLockList.contains(type);
    }

    /**
     * 出售产业
     */
    public int soldIndustry(int id, int num) {
        int ret = checkOpen();
        if (ret != 0) return ret;

//        if(userData.getTradeStatus().isIll()){
//            return GameErrorCode.E_GREAT_TRADE_CURR_YEAR_ILL;
//        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();
        GreatTradeGoodsInfo goodsInfo = config.getGreatTradeGoodsInfo(id);
        if(goodsInfo == null){
            return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
        }

        List<Integer> unLockList = config.getUnLockType(userData.getTradeStatus().getTitle());
        if(!unLockList.contains(3)){
            return GameErrorCode.E_GREAT_TRADE_INDUSTRY_LOCK;
        }

        if(userData.getIndustry().getId() != id){
            return GameErrorCode.E_GREAT_TRADE_CAN_NOT_SOLD_INDUSTRY;
        }

        if(num > userData.getIndustry().getShares()){
            return GameErrorCode.E_GREAT_TRADE_INDUSTRY_NO_ENOUGH;
        }

        //产业发展期
        List<Integer> exParamList = StringUtils.stringToIntegerList(goodsInfo.getExParam(), "\\|");
        if(userData.getIndustry().getId() > 0 && (userData.getTradeStatus().getCurYear() - userData.getIndustry().getStartYear()
                < exParamList.get(0))){
            return GameErrorCode.E_GREAT_TRADE_CAN_NOT_SOLD_INDUSTRY;
        }

        BigInteger add = BigInteger.valueOf(userData.getIndustry().getPrice()).multiply(BigInteger.valueOf(num));

        GreatTradeIndustry oldIndustry = userData.getIndustry();
        if(num == userData.getIndustry().getShares()){
            userData.setIndustry(new GreatTradeIndustry());
        }else {
            userData.getIndustry().setShares(userData.getIndustry().getShares() - num);
        }

        userData.getTradeStatus().setSilver(new BigInteger(userData.getTradeStatus().getSilver()).add(add).toString());
        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);
        userData.setUpdateOption();

        GreatTradeProto.GreatTradeIndustrySoldRespMsg.Builder respMsg = GreatTradeProto.GreatTradeIndustrySoldRespMsg.newBuilder().setRet(0);
        respMsg.setReward(add.toString());
        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_INDUSTRY_SOLD, respMsg);

        //日志
        AutoLogMgr.add(new LogGreatTradeIndustry(player.getUserId(), config.getActivityId(), oldIndustry.getId(),
            0, num, add.toString(), userData.getTotalTradeTimes()));

        return 0;
    }

    /**
     * 下一年
     */
    public int nextYear() {

        int ret = checkOpen();
        if (ret != 0) return ret;

        //是否结算
        boolean close = false;
        if(userData.getTradeStatus().isIll()){
            close = true;
        }
        GreatTradeConfig config = GreatTradeMgr.getConfig();
        //缓存计算结果
        GreatTradeSimpleStatus tempStatus = new GreatTradeSimpleStatus();
        GreatTradeMgr.copy(userData.getTradeStatus(), tempStatus);
        //恢复形象状态
        if(tempStatus.getStatus() != 2) {
            tempStatus.setStatus(0);
        }
        //重置每年售卖次数
        tempStatus.setSellTimes(0);

        GreatTradeProto.GreatTradeNextYearRespMsg.Builder respMsg = GreatTradeProto.GreatTradeNextYearRespMsg.newBuilder();
        GreatTradeTitleInfo titleInfo = config.getGreatTradeTitleInfo(userData.getTradeStatus().getTitle());
        //称号变更
        int addTitlePrestige = 0;
        //随机监管风险
        int oldRisk = tempStatus.getRisk();
        //盐场风险与收益
        List<SaltWorksResult> saltWorksResults = new ArrayList<>();
        //产业风险与收益
        IndustryResult industryResult = null;

        if (!close) {

            //资产结算
            BigInteger sliver = new BigInteger(tempStatus.getSilver());

            industryResult = GreatTradeMgr.calIndustryProfit(userData.getBeautyMap(), userData.getIndustry(), null, config, tempStatus.getCurYear(), random);

            BigInteger industryAdd = industryResult.getIndustryProfit().add(industryResult.getAddSliverOfBroken());
            if (industryResult.getAddSliverOfBroken().compareTo(BigInteger.ZERO) > 0) {
                if (tempStatus.getStatus() < 1) {
                    tempStatus.setStatus(1);
                }
            }
            tempStatus.addSellMoney(1, industryAdd);
            sliver = sliver.add(industryAdd);


            saltWorksResults = GreatTradeMgr.calSaltWorksResults(userData.getBeautyMap(), tempStatus, userData.getSaltWorksMap(), config, random);
            for (SaltWorksResult saltWorksResult : saltWorksResults) {
                //开采有钱
                if (saltWorksResult.getRet() == 2) {
                    sliver = sliver.add(saltWorksResult.getAddSliver());
                }
            }

            tempStatus.setSilver(sliver.toString());
            GreatTradeMgr.calUserAssert(userData, tempStatus, config);

            //寿辰事件 加现银
            BigInteger addBirthSliver = GreatTradeMgr.calYearBirthEvent(tempStatus, config);

            if (addBirthSliver.compareTo(BigInteger.ZERO) > 0) {
                respMsg.addEvent(GreatTradeProto.GreatTradeEventViewTemp.newBuilder().setType(1).setValue(addBirthSliver.toString()));
            }

            //健康事件
            HealthResult healthResult = calYearHealthEvent(tempStatus, config, random, false);

            if (tempStatus.isIll()) {
                respMsg.addEvent(GreatTradeProto.GreatTradeEventViewTemp.newBuilder().setType(6));
            }

            //增加外出次数据
            if (isUnLockTypeByTitle(config, 2)) {
                int addOutTimes = 0;
                if (config.getOutAddNum().get(0) == 1 || (tempStatus.getCurYear() > 1 && tempStatus.getCurYear() % (config.getOutAddNum().get(0)) == 0)) {
                    addOutTimes += config.getOutAddNum().get(1);
                }
                addOutTimes += GreatTradeMgr.getSkillAddition(12, userData.getBeautyMap(), tempStatus.getCurYear(), null, config);
                if (addOutTimes > 0 && tempStatus.getOutTimes() < config.getOutMax()) {
                    tempStatus.setOutTimes(Math.min(addOutTimes + tempStatus.getOutTimes(), config.getOutMax()));
                }
            }

            sliver = sliver.add(addBirthSliver);
            tempStatus.setSilver(sliver.toString());
            //年龄+1
            tempStatus.setAge(tempStatus.getAge() + 1);
            tempStatus.setCurYear(1 + tempStatus.getCurYear());

            if (healthResult.getSubHealth() > 0) {
                respMsg.addEvent(GreatTradeProto.GreatTradeEventViewTemp.newBuilder().setType(3).setValue(healthResult.getSubHealth() + ""));
            }

            GreatTradeMgr.calUserAssert(userData, tempStatus, config);

            Map<Integer, Integer> goodsPriceMap = GreatTradeMgr.initYearMarketGoodsPrice(userData, tempStatus, config, random);

            //产业破产
            if (industryResult.getAddSliverOfBroken().compareTo(BigInteger.ZERO) > 0) {
                respMsg.addEvent(GreatTradeProto.GreatTradeEventViewTemp.newBuilder().setType(5).setNpcId(userData.getIndustry().getId()).setValue(industryResult.getAddSliverOfBroken().toString()));
                userData.getTradeStatus().setBrokenTimes(1 + userData.getTradeStatus().getBrokenTimes());
                userData.setIndustry(new GreatTradeIndustry());
            } else {
                //盈亏
                long yk = GreatTradeMgr.getPriceCompare(userData.getIndustryPrice(), userData.getIndustry().getId());
                userData.getIndustry().setLastCondition(yk);
            }

            //盐场查封
            for (SaltWorksResult saltWorksResult : saltWorksResults) {
                GreatTradeSaltWorks saltWorks = userData.getSaltWorksMap().get(saltWorksResult.getId());
                if (saltWorks != null) {
                    if (saltWorksResult.getRet() == 1) {
                        saltWorks.setSealOrSell(1);
                        respMsg.addEvent(GreatTradeProto.GreatTradeEventViewTemp.newBuilder().setType(4).setNpcId(saltWorks.getId()));
                        continue;
                    }
                    if (saltWorksResult.getRet() == 3) {
                        continue;
                    }
                    saltWorks.setUse(saltWorks.getUse() + saltWorksResult.getLose());
                }
            }

            respMsg.setOldTitle(userData.getTradeStatus().getTitle());
            tempStatus.setRisk(config.getRandomSaltRisk(random));

            userData.setGoodsPriceList(goodsPriceMap);
            GreatTradeMgr.copy(tempStatus, userData.getTradeStatus());
            GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);
            userData.getTradeStatus().setLastAssets(userData.getTradeStatus().getAssets());

            if (healthResult.getRandomEventId() > 0 && tempStatus.getRandomEventId() == 0) {
                userData.getTradeStatus().setRandomEventId(healthResult.getRandomEventId());
                respMsg.addEvent(GreatTradeProto.GreatTradeEventViewTemp.newBuilder().setType(2).setType(healthResult.getRandomEventId()));
            }

            int oldTitleId = userData.getTradeStatus().getTitle();
            Property titleReward = checkTitleInfoChange(userData.getTradeStatus().getTitle(), userData.getTradeStatus(), config);
            if (titleReward != null) {
                respMsg.setOldTitle(oldTitleId);
            }

            if (titleReward != null) {
                //名望奖励
                changeTradeResource(userData.getTradeStatus(), titleReward, config);
                addTitlePrestige = titleReward.getCountByGoodsId(eGreatTradeAttrs.Prestige.getId()).intValue();
                addTitleChangeMilepostRecord(userData, userData.getTradeStatus().getTitle(), 0, 0, 0);
                syncTitleChange(userData.getTradeStatus(), PropertyHelper.parsePropertyToString(titleReward));
                calPrestige(userData.getTradeStatus(), config, true);
                checkSkillUnlock("4", "" + userData.getTradeStatus().getTitle(), "1", config);
            }

            addYearProfitRecord(industryResult, saltWorksResults, healthResult.getSkillAdd(), BigInteger.ZERO);

            initAllEvent(userData, config);
            userData.setUpdateOption();

            titleInfo = config.getGreatTradeTitleInfo(userData.getTradeStatus().getTitle());


            notifySaltWorksCondition();
            notifyGoodsYingLiCondition(config);

            //称号达成
            checkSkillUnlock("4", "" + titleInfo.getId(), "1", config);

            //资产达成
            player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(new BigInteger(userData.getTradeStatus().getAssets()), 2));
        }

        if(close) {
            //结算
            closeTrade(true, config);

            Property endProperty = PropertyHelper.parseStringToProperty(titleInfo.getEndReward());

            player.getModule(CurrencyModule.class).addCurrency(endProperty, eLogMoneyType.GreatTradeActivity, eLogMoneyType.GreatTradeActivityEndTradeNormalReward);
            respMsg.setReward(PropertyHelper.parsePropertyToString(endProperty));

            userData.setUpdateOption();

            for (GreatTradeMilepostRecord milepostRecord : userData.getMilepostRecordList()) {
                respMsg.addMilepost(GreatTradeActivityPb.buildMilepost(milepostRecord));
            }
        }

        respMsg.setSettle(close);
        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        respMsg.setRet(0);
        respMsg.setSettle(close);
        respMsg.setAddTitlePrestige(addTitlePrestige);
        buildYearProfit(userData, respMsg);
        player.sendPacket(Protocol.U_GREAT_TRADE_NEXT_YEAR, respMsg);

        //盐场收益日志
        for (SaltWorksResult worksResult : saltWorksResults) {
            GreatTradeSaltWorks saltWorks = userData.getSaltWorksMap().get(worksResult.getId());
            int type = 0;
            if(worksResult.getRet() == 0){
                type = 2;
            }else if(worksResult.getRet() == 1){
                type = 4;
            }else if(worksResult.getRet() == 2){
                type = 3;
            }
            if(type > 0){
                AutoLogMgr.add(new LogGreatTradeSaltWorks(player.getUserId(), config.getActivityId(), worksResult.getId(), type, saltWorks.getMiningSpeed(),
                        GreatTradeMgr.getSaltWorksReserves(userData, saltWorks, config),
                        oldRisk, worksResult.getLose() + "", worksResult.getAddSliver().toString(), userData.getTotalTradeTimes()));

                //累计盐场收益
                BigInteger saltWorksProfit = new BigInteger(userData.getTradeStatus().getSaltWorksProfit());
                userData.getTradeStatus().setSaltWorksProfit(saltWorksProfit.add(worksResult.getAddSliver()).toString());
                userData.setUpdateOption();
            }
        }

        //产业收益日志
        if(industryResult != null && industryResult.getIndustryProfit().compareTo(BigInteger.ZERO) > 0){
            AutoLogMgr.add(new LogGreatTradeIndustryProfit(player.getUserId(), config.getActivityId(), userData.getIndustry().getId(),
                    industryResult.getIndustryProfit().toString(), userData.getTradeStatus().getAge(), userData.getTotalTradeTimes()));

            //累计产业收益
            BigInteger industryProfit = new BigInteger(userData.getTradeStatus().getIndustryProfit());
            userData.getTradeStatus().setIndustryProfit(industryProfit.add(industryResult.getIndustryProfit()).toString());
        }
        return 0;
    }

    private void notifyGoodsYingLiCondition(GreatTradeConfig config) {
        BigInteger add = new BigInteger(userData.getTradeStatus().getGooodsAddSum());
        if(add.compareTo(BigInteger.ZERO) > 0){
            userData.getTradeStatus().setYingLi(1 + userData.getTradeStatus().getYingLi());
            checkSkillUnlock("8", "0", "" + userData.getTradeStatus().getYingLi(), config);
        }else {
            userData.getTradeStatus().setYingLi(0);
        }
        //每年重置
        userData.getTradeStatus().setGooodsAddSum("0");
        userData.setUpdateOption();
    }

    public void notifySaltWorksCondition() {
        //查封成就
        int sealNum = 0;
        for (Map.Entry<Integer, GreatTradeSaltWorks> worksEntry : userData.getSaltWorksMap().entrySet()) {
            GreatTradeSaltWorks saltWorks = worksEntry.getValue();
            if(saltWorks.getSealOrSell() == 1){
                sealNum++;
            }
        }
        if(sealNum > 0){
            player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(BigInteger.valueOf(sealNum), 11));
        }
    }

    /**
     * 称号是否变更
     */
    private Property checkTitleInfoChange(int oldTitle, GreatTradeSimpleStatus tempStatus, GreatTradeConfig config) {
        Property titleReward = null;
        //新称号
        GreatTradeTitleInfo titleInfo = config.getTitleInfoByAssets(tempStatus.getAssets());
        if(titleInfo == null){
            titleInfo = config.getTitleInfoList().get(0);
        }
        if(titleInfo.getId() > oldTitle){
            titleReward = config.getTitleRewardByTitleId(oldTitle, titleInfo.getId());
            tempStatus.setTitle(titleInfo.getId());
        }
        return titleReward;
    }

    /**
     * 名望是否变更
     */
    public boolean calPrestige(GreatTradeSimpleStatus status, GreatTradeConfig config, boolean notify){
        List<String> param1 = StringUtils.stringToStringList(config.getResultFame(), "\\|");
        int nowLv = -1;
        List<Long> addList = new ArrayList<>();
        for (String param2 : param1) {
            List<Long> rangeList = StringUtils.stringToLongList(param2, ";");
            addList.add(rangeList.get(1));
            if(status.getPrestige() >= rangeList.get(0)){
                nowLv++;
            }
        }
        boolean changed = false;
        if(nowLv > status.getPrestigeLv()){
            changed = true;
            for(int i = status.getPrestigeLv() + 1; i <= nowLv && i < addList.size(); i++) {
                status.setBagCap(status.getBagCap() + addList.get(i).intValue());
            }
            status.setPrestigeLv(nowLv);
        }
        if(changed && notify){
            player.sendPacket(Protocol.U_GREAT_TRADE_ATTR_UPGRADE_SYNC, GreatTradeProto.GreatTradeUserAttributeUpgradeSync.newBuilder().setType(2).setLv(nowLv));
        }
        checkSkillUnlock("9", "0", status.getPrestige() + "", config);
        return changed;
    }

    public void syncTitleChange(GreatTradeSimpleStatus status, String reward){
        player.sendPacket(Protocol.U_GREAT_TRADE_ATTR_UPGRADE_SYNC, GreatTradeProto.GreatTradeUserAttributeUpgradeSync.newBuilder().setType(1).setLv(status.getTitle()).setReward(reward));
    }

    /**
     * 流年小报
     */
    public int allTabloid() {
        int ret = checkOpen();
        if (ret != 0) return ret;

        GreatTradeProto.GreatTradeTabloidRespMsg.Builder respMsg = GreatTradeProto.GreatTradeTabloidRespMsg.newBuilder();
        int size = userData.getGoodsHistoryPrice().size();
        if(size > 0) {
            for (Map.Entry<Integer, List<Integer>> entry : userData.getGoodsHistoryPrice().entrySet()) {
                GreatTradeProto.GreatTradeTabloidTempMsg.Builder builder = GreatTradeProto.GreatTradeTabloidTempMsg.newBuilder();
                builder.setItemId(entry.getKey());
                for (int val : entry.getValue()) {
                    GreatTradeProto.GreatTradeItemValueTemp.Builder value = GreatTradeProto.GreatTradeItemValueTemp.newBuilder();
                    value.setValue(val);
                    value.setId(entry.getKey());
                    builder.addData(value);
                }
                respMsg.addTabloid(builder);
            }

        }

        //盐场
        player.sendPacket(Protocol.U_GREAT_TRADE_TABLOID, respMsg.setRet(0));

        return 0;
    }

    /**
     * 初始所有类型外出事件
     */
    private void initAllEvent(UserGreatTradeData userData, GreatTradeConfig config) {
        initEvent(1, userData, config);
        initEvent(2, userData, config);
        initEvent(3, userData, config);
        initEvent(4, userData, config);
        initEvent(5, userData, config);
        initEvent(6, userData, config);
    }

    /**
     * 初始外出事件
     */
    private void initEvent(int type, UserGreatTradeData userData, GreatTradeConfig config) {
        //1\医馆|2\酒楼|3\御街|4\黑市
        int areaId = 1;
        if(type == 1 || type == 2){
            areaId = 2;
        }else if(type == 5){
            areaId = 3;
        }else if(type == 6) {
            areaId = 4;
        }
        GreatTradeAreaEvent event = new GreatTradeAreaEvent(areaId);
        event.setEventType(type);
        if(type <= 4){
            List<GreatTradeEventInfo> eventInfoList = config.getGreatTradeEventInfoByType(event.getEventType());
            if(eventInfoList.size() == 1) {
                event.setEventId(eventInfoList.get(0).getId());
            }else if(eventInfoList.size() > 1){
                int idx = random.nextInt(eventInfoList.size());
                event.setEventId(eventInfoList.get(idx).getId());
            }else {
                log.error("event type {} config zero", type);
            }
        }else if(type == 5){
            event.setEventType(type);
        }else if(type == 6){
            initHeiShiEvent(config, event, userData);
        }
        userData.getAreaEventMap().put(type, event);
    }

    /**
     * 初始黑市事件
     */
    private void initHeiShiEvent(GreatTradeConfig config, GreatTradeAreaEvent event, UserGreatTradeData userData) {
        List<Integer> wList;
        List<GreatTradeEventInfo> eventInfoList;
        int idx;
        event.setEventType(6);

        wList = new ArrayList<>();
        eventInfoList = config.getGreatTradeEventInfoByType(event.getEventType());
        for (GreatTradeEventInfo eventInfo : eventInfoList) {
            List<Integer> list = StringUtils.stringToIntegerList(eventInfo.getExParam(), "\\|");
            wList.add(list.get(1));
        }
        idx = RandomHelper.getRandomIndexByWeight(wList, random);
        GreatTradeEventInfo eventInfo = eventInfoList.get(idx);
        event.setEventId(eventInfo.getId());
        //临时加了 黑市资产最大值限制 min(玩家资产，参数)
        BigInteger param = BigInteger.ZERO;
        Map<String, ActivityConfig> configMap = NormalActivityMgr.getActivityConfigMap(config.getActivityId());
        if(configMap != null){
            ActivityConfig activityConfig = configMap.get("BIGSHOP_OUT_BLACK_MARKET_MONEY");
            if(activityConfig != null){
                param = new BigInteger(activityConfig.getValue());
            }
        }
        //名望
        BigInteger buyPrice = config.getTreasurePriceByPrestige(userData.getTradeStatus().getPrestige(), random, userData);
        event.setPrice(buyPrice.toString());

        //临时
        if(param.compareTo(BigInteger.ZERO) > 0 && new BigInteger(userData.getTradeStatus().getAssets()).compareTo(param) > 0){
            UserGreatTradeData tempUserData = new UserGreatTradeData();
            GreatTradeSimpleStatus tempStatus = new GreatTradeSimpleStatus();
            GreatTradeMgr.copy(userData.getTradeStatus(), tempStatus);
            tempStatus.setAssets(param.toString());
            tempUserData.setTradeStatus(tempStatus);
            buyPrice = config.getTreasurePriceByPrestige(tempUserData.getTradeStatus().getPrestige(), random, tempUserData);
            event.setPrice(buyPrice.toString());
        }
    }

    /**
     * 处理外出事件
     */
    public int handleAreaEvent(int eventType, int opt) {

        int ret = checkOpen();
        if (ret != 0) return ret;

//        if(userData.getTradeStatus().isIll()){
//            return GameErrorCode.E_GREAT_TRADE_CURR_YEAR_ILL;
//        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        if(!isUnLockTypeByTitle(config, 2)){
            return GameErrorCode.E_GREAT_TRADE_AREA_OUT_LOCK;
        }

        GreatTradeAreaEvent areaEvent = userData.getAreaEventMap().get(eventType);
        if(areaEvent.getEventType() <= 0){
            return GameErrorCode.E_GREAT_TRADE_AREA_EVENT_HAD_HANDLE;
        }

        GreatTradeProto.DoGreatTradeAreaEventRespMsg.Builder respMsg = GreatTradeProto.DoGreatTradeAreaEventRespMsg.newBuilder().setRet(0);
        boolean done = false;
        int areaId = areaEvent.getAreaId();
        if(areaEvent.getEventType() == 5){
            //御街翻牌
            if(opt == -1){
                //放弃、跳过
                initEvent(5, userData, config);
            }else {
                if(opt < 1 || opt > 3){
                    return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
                }
                //首次翻牌，判定外出次数
                if(areaEvent.getSelectList().size() == 0){
                    if(userData.getTradeStatus().getOutTimes() <= 0){
                        return GameErrorCode.E_GREAT_TRADE_NO_OUT_AREA_TIMES;
                    }
                }
                //翻牌
                if(areaEvent.getSelectIdxList().contains(opt)){
                    return GameErrorCode.E_GREAT_TRADE_AREA_EVENT_HAD_HANDLE;
                }
                if(areaEvent.getSelectList().size() > 0) {
                    //处理消耗,不足让翻牌
                    BigInteger silver = new BigInteger(userData.getTradeStatus().getSilver());
                    int addition = config.getOutFlopCost().get(areaEvent.getSelectList().size());
                    BigInteger cost = GreatTradeMgr.toPositive(new BigDecimal(GreatTradeMgr.getCalAbleAssets(userData.getTradeStatus().getAssets())).multiply(BigDecimal.valueOf(addition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).toBigInteger());
                    if (silver.compareTo(BigInteger.ZERO) <= 0 || silver.compareTo(cost) < 0) {
                        return GameErrorCode.E_GREAT_TRADE_SLIVER_NO_ENOUGH;
                    }
                    userData.getTradeStatus().setSilver(silver.subtract(cost).toString());
                }
                List<GreatTradeEventInfo> list = config.getGreatTradeEventInfoByType(5);
                list.removeIf(eventInfo -> areaEvent.getSelectList().contains(eventInfo.getId()));
                List<Integer> weightList = new ArrayList<>();
                for (GreatTradeEventInfo eventInfo : list) {
                    weightList.add(StringUtils.stringToIntegerList(eventInfo.getExParam(), "\\|").get(0));
                }
                int idx = RandomHelper.getRandomIndexByWeight(weightList, random);
                GreatTradeEventInfo eventInfo = list.get(idx);
                areaEvent.getSelectIdxList().add(opt);
                areaEvent.getSelectList().add(eventInfo.getId());
                //处理奖励
                Property reward = PropertyHelper.parseStringToProperty(eventInfo.getReward());
                //处理银两千分比
                long silverAddition = reward.getCountByGoodsId(eGreatTradeAttrs.Sliver.getId()).longValue();
                if(silverAddition != 0){
                    silverAddition = BigDecimal.valueOf(silverAddition).multiply(new BigDecimal(GreatTradeMgr.getCalAbleAssets(userData.getTradeStatus().getAssets()))).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).longValue();
                    reward.setGood(eGreatTradeAttrs.Sliver.getId(), BigInteger.valueOf(silverAddition));
                }
                changeTradeResource(userData.getTradeStatus(), reward, config);
                List<Long> rewardList = StringUtils.stringToLongList(eventInfo.getReward(), "=");
                if(silverAddition != 0){
                    areaEvent.getValList().add(silverAddition);
                }else {
                    areaEvent.getValList().add(rewardList.get(1));
                }
                if(rewardList.get(1) < 0){
                    respMsg.setConsume(rewardList.get(0) + "=" + (0 - (silverAddition != 0 ? silverAddition : rewardList.get(1))));
                }else {
                    respMsg.setReward(rewardList.get(0) + "=" + (silverAddition != 0? silverAddition : rewardList.get(1)));
                }
                respMsg.addAllEventId(areaEvent.getSelectList());
                if(areaEvent.getSelectIdxList().size() == 3){
                    initEvent(5, userData, config);
                }else if(areaEvent.getSelectList().size() == 1){
                    //首次翻牌扣次数
                    done = true;
                }
                GreatTradeMgr.completeAreaEvent(player, userData, eventInfo.getId(), config);
            }
        }else {
            //医馆等其他事件已确定eventId
            GreatTradeEventInfo eventInfo = config.getGreatTradeEventInfo(areaEvent.getEventId());
            if(eventInfo == null) {
                return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
            }
            //判定外出次数
            if(userData.getTradeStatus().getOutTimes() <= 0){
                return GameErrorCode.E_GREAT_TRADE_NO_OUT_AREA_TIMES;
            }

            if(areaId == 1){
                if(areaEvent.getEventType() == 3){
                    //老中医
                    if(opt == 1){
                        BigInteger cost = BigDecimal.valueOf(config.getOutParamHospital().get(0)).multiply(BigDecimal.valueOf(Math.pow(1 + (double)config.getOutParamHospital().get(1) / 1000, userData.getTradeStatus().getHealthTimes()))).toBigInteger();
                        if(new BigInteger(userData.getTradeStatus().getSilver()).compareTo(cost) < 0){
                            return GameErrorCode.E_GREAT_TRADE_SLIVER_NO_ENOUGH;
                        }
                        respMsg.setConsume(eGreatTradeAttrs.Sliver.getId() + "=" + cost);
                        consumeTradeResource(userData.getTradeStatus(),PropertyHelper.parseStringToProperty(respMsg.getConsume()), config);
                        respMsg.setReward(eventInfo.getReward());
                        changeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(eventInfo.getReward()), config);
                        userData.getTradeStatus().setHealthTimes(1 + userData.getTradeStatus().getHealthTimes());
                    }
                    initEvent(3, userData, config);
                    done = true;
                    GreatTradeMgr.completeAreaEvent(player, userData, eventInfo.getId(), config);
                }else if(areaEvent.getEventType() == 4){
                    //入殓师
                    if(opt == 1){
                        respMsg.setConsume(eGreatTradeAttrs.Health.getId() + "=" + config.getOutParamHospital().get(2));
                        consumeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(respMsg.getConsume()), config);
                        //扣上限
                        int sub = config.getOutParamHospital().get(2);
                        int max = GreatTradeMgr.getUserMaxHealth(userData, config, userData.getTradeStatus().getExMaxHealth());
                        sub = Math.min(sub, max);
                        userData.getTradeStatus().setExMaxHealth(userData.getTradeStatus().getExMaxHealth() - sub);
                        max = GreatTradeMgr.getUserMaxHealth(userData, config, userData.getTradeStatus().getExMaxHealth());
                        if(userData.getTradeStatus().getHealth() > max){
                            userData.getTradeStatus().setHealth(max);
                            checkHealthValid(userData.getTradeStatus(), 0, userData.getBeautyMap(), config);
                        }
                        respMsg.setReward(eGreatTradeAttrs.Sliver.getId() + "=" + GreatTradeMgr.getCalAblePrestige(userData.getTradeStatus()) * config.getOutParamHospital().get(3));
                        changeTradeResource(userData.getTradeStatus(),PropertyHelper.parseStringToProperty(respMsg.getReward()), config);
                    }
                    initEvent(4, userData, config);
                    done = true;
                    GreatTradeMgr.completeAreaEvent(player, userData, eventInfo.getId(), config);
                }
            }else if(areaId == 2) {
                //酒楼
                if(areaEvent.getEventType() == 1){
                    //题目
                    List<Integer> exParamList = StringUtils.stringToIntegerList(eventInfo.getExParam(), "\\|");
                    if(opt == exParamList.get(0)){
                        respMsg.setReward(eventInfo.getReward());
                        changeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(eventInfo.getReward()), config);
                        respMsg.setSuccess(true);
                    }else {

                        respMsg.setSuccess(false);
                    }
                    initEvent(1, userData, config);
                    done = true;
                    GreatTradeMgr.completeAreaEvent(player, userData, eventInfo.getId(), config);
                }else if(areaEvent.getEventType() == 2){
                    //选项一成功概率；选项一直接条件；损失
                    List<String> exParamList = StringUtils.stringToStringList(eventInfo.getExParam(), "\\|");
                    List<String> rewardList = StringUtils.stringToStringList(eventInfo.getReward(), "\\|");
                    if(opt == 1) {
                        int weight = Integer.valueOf(exParamList.get(0));
                        int times = userData.getTradeStatus().getBanquetTimes();
                        BigInteger cost = BigDecimal.valueOf(config.getOutParamRestaurantList().get(0)).multiply(BigDecimal.valueOf(Math.pow(1 + (double)config.getOutParamRestaurantList().get(1) / 1000, times))).toBigInteger();
                        if(cost.compareTo(new BigInteger(userData.getTradeStatus().getSilver())) > 0){
                            return GameErrorCode.E_GREAT_TRADE_SLIVER_NO_ENOUGH;
                        }
                        //消耗
                        if (random.nextInt(1000) < weight) {
                            //成功
                            changeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(rewardList.get(0)), config);
                            respMsg.setReward(rewardList.get(0));
                            respMsg.setSuccess(true);
                        } else {
                            //失败
                            changeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(rewardList.get(1)), config);
                            respMsg.setReward(rewardList.get(1));
                            respMsg.setSuccess(false);
                        }
                        userData.getTradeStatus().setBanquetTimes(times + 1);
                        //消耗
                        respMsg.setConsume(eGreatTradeAttrs.Sliver.getId() + "=" + cost);
                        consumeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(respMsg.getConsume()), config);
                    }else if(opt == 2){
                        //名望换现银
                        String cost = eGreatTradeAttrs.Prestige.getId() + "=" + config.getOutParamRestaurantList().get(2);
                        if(!isEnough(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(cost))){
                            return 8607;//暂时
                        }
                        int weight = Integer.valueOf(exParamList.get(1));
                        if (random.nextInt(1000) < weight) {
                            //成功
                            Property property = PropertyHelper.parseStringToProperty(rewardList.get(2));
                            for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
                                BigInteger val = new BigDecimal(userData.getTradeStatus().getAssets()).multiply(new BigDecimal(entry.getValue())).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).toBigInteger();
                                entry.setValue(val);
                            }
                            changeTradeResource(userData.getTradeStatus(), property, config);
                            respMsg.setReward(PropertyHelper.parsePropertyToString(property));
                            respMsg.setSuccess(true);
                        }else {
                            Property property = PropertyHelper.parseStringToProperty(rewardList.get(3));
                            for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
                                BigInteger val = new BigDecimal(userData.getTradeStatus().getAssets()).multiply(new BigDecimal(entry.getValue())).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).toBigInteger();
                                entry.setValue(val);
                            }
                            changeTradeResource(userData.getTradeStatus(), property, config);
                            respMsg.setReward(PropertyHelper.parsePropertyToString(property));
                            respMsg.setSuccess(false);
                        }
                        consumeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(cost), config);
                    }
                    initEvent(2, userData, config);
                    done = true;
                    GreatTradeMgr.completeAreaEvent(player, userData, eventInfo.getId(), config);
                }
            }else if(areaId == 4){
                //黑市
                if(opt == 1){
                    BigInteger get = new BigDecimal(areaEvent.getPrice()).multiply(new BigDecimal(eventInfo.getReward()))
                            .divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).toBigInteger();
                    BigInteger cost = new BigInteger(areaEvent.getPrice());
                    if(new BigInteger(userData.getTradeStatus().getSilver()).compareTo(cost) < 0){
                        return GameErrorCode.E_GREAT_TRADE_SLIVER_NO_ENOUGH;
                    }

                    respMsg.setReward(eGreatTradeAttrs.Sliver.getId() + "=" + get);
                    respMsg.setConsume(eGreatTradeAttrs.Sliver.getId() + "=" + areaEvent.getPrice());
                    if(get.compareTo(cost) > 0){
                        BigInteger add = get.subtract(cost);
                        int addition = GreatTradeMgr.getSkillAddition(14, userData.getBeautyMap(), null, null, config);
                        if(addition > 0){
                            add = new BigDecimal(add).multiply(BigDecimal.valueOf(addition + 1000)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).toBigInteger();
                        }
                        userData.getTradeStatus().setSilver(new BigInteger(userData.getTradeStatus().getSilver()).add(add).toString());
                    }else{
                        userData.getTradeStatus().setSilver(new BigInteger(userData.getTradeStatus().getSilver()).subtract(cost.subtract(get)).toString());
                    }
                    //changeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(respMsg.getReward()), config);
                    //consumeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(respMsg.getConsume()), config);

                    List<Integer> exParamList = StringUtils.stringToIntegerList(eventInfo.getExParam(), "\\|");
                    if(exParamList.get(2) >= 4){
                        userData.getTradeStatus().setKbpjTimes(1 + userData.getTradeStatus().getKbpjTimes());
                        player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(BigInteger.valueOf(userData.getTradeStatus().getKbpjTimes()), 7));
                    }else {
                        userData.getTradeStatus().setKbpjTimes(0);
                    }
                    if(exParamList.get(2) >= 4){
                        List<Integer> paramList = new ArrayList<>();
                        paramList.add(eventInfo.getId());
                        paramList.add(exParamList.get(2));
                        addMilepostRecord(5, userData.getTradeStatus().getAge(), paramList);
                    }
                }
                initEvent(6, userData, config);
                done = true;
                GreatTradeMgr.completeAreaEvent(player, userData, eventInfo.getId(), config);
                checkSkillUnlock("7", "0", "" + userData.getEventMap().getOrDefault(4, 0), config);
            }
        }

        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);

        if(done){
            //次数扣减
            userData.getTradeStatus().setOutTimes(userData.getTradeStatus().getOutTimes() - 1);
            userData.getTradeStatus().setTotalOutTimes(userData.getTradeStatus().getTotalOutTimes() + 1);

            //遭遇次数
            player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(BigInteger.ONE, 3));

            //健康点流失
            if(userData.getTradeStatus().getTotalOutTimes() % config.getHealthyLoseOut().get(0) == 0){
                consumeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(eGreatTradeAttrs.Health.getId() + "=" + config.getHealthyLoseOut().get(1)), config);
            }

            //事件收益日志
            addEventSliverProfit(respMsg.getReward(), respMsg.getConsume(), userData.getTradeStatus());

            //userData.setUpdateOption();

            //日志
            AutoLogMgr.add(new LogGreatTradeEvent(player.getUserId(), config.getActivityId(), areaId, areaEvent.getEventId(), opt,
                    respMsg.getReward() == null ? "" : respMsg.getReward(), respMsg.getConsume() == null ? "" : respMsg.getConsume(),
                    getUserAttrValue(userData.getTradeStatus()), userData.getTradeStatus().getAge(), userData.getTotalTradeTimes()));
        }

        userData.setUpdateOption();

        Property titleReward = checkTitleInfoChange(userData.getTradeStatus().getTitle(), userData.getTradeStatus(), config);
        if(titleReward != null) {
            changeTradeResource(userData.getTradeStatus(), titleReward, config);
            addTitleChangeMilepostRecord(userData, userData.getTradeStatus().getTitle(), 2, areaEvent.getAreaId(),areaEvent.getEventId());
            syncTitleChange(userData.getTradeStatus(), PropertyHelper.parsePropertyToString(titleReward));
            calPrestige(userData.getTradeStatus(), config, true);
            checkSkillUnlock("4", "" + userData.getTradeStatus().getTitle(), "1", config);
            userData.setUpdateOption();
        }else {
            calPrestige(userData.getTradeStatus(), config, true);
            userData.setUpdateOption();
        }

        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_AREA_HANDLE, respMsg);
        return 0;
    }

    /**
     * 处理随机事件
     */
    public int handleRandomEvent(int select) {

        int ret = checkOpen();
        if (ret != 0) return ret;

//        if(userData.getTradeStatus().isIll()){
//            return GameErrorCode.E_GREAT_TRADE_CURR_YEAR_ILL;
//        }

        if(userData.getTradeStatus().getRandomEventId() == 0){
            return GameErrorCode.E_GREAT_TRADE_RANDOM_EVENT_HAD_HANDLE;
        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();
        GreatTradeEventInfo eventInfo = config.getGreatTradeEventInfo(userData.getTradeStatus().getRandomEventId());
        if(eventInfo == null){
            return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
        }

        int randomEventId = userData.getTradeStatus().getRandomEventId();
        GreatTradeProto.HandleGreatTradeRandomEventRespMsg.Builder respMsg = GreatTradeProto.HandleGreatTradeRandomEventRespMsg.newBuilder();
        //选项一成功概率；选项一直接条件；损失
        List<String> exParamList = StringUtils.stringToStringList(eventInfo.getExParam(), "\\|");
        List<String> rewardList = StringUtils.stringToStringList(eventInfo.getReward(), "\\|");
        String consume = "";
        if(select == 1){
            int weight = Integer.valueOf(exParamList.get(0));
            if(!"0".equals(exParamList.get(2)) && !isEnough(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(exParamList.get(2)))){
                userData.getTradeStatus().setRandomEventId(0);
                userData.setUpdateOption();
                syncUserData();
                return GameErrorCode.E_GREAT_TRADE_SLIVER_NO_ENOUGH;
            }
            if(weight <= 0){
                //不走概率
                changeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(rewardList.get(0)), config);
                respMsg.setReward(rewardList.get(0));
                respMsg.setSuccess(true);
            }else {
                if (isEnough(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(exParamList.get(1))) || random.nextInt(1000) < weight) {
                    //成功
                    changeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(rewardList.get(0)), config);
                    respMsg.setReward(rewardList.get(0));
                    respMsg.setSuccess(true);
                } else {
                    //失败
                    changeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(rewardList.get(1)), config);
                    respMsg.setReward(rewardList.get(1));
                    respMsg.setSuccess(false);
                }
            }
            //消耗
            consumeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(exParamList.get(2)), config);
            consume = exParamList.get(2);

        }else if(select == 2){
            changeTradeResource(userData.getTradeStatus(), PropertyHelper.parseStringToProperty(rewardList.get(2)), config);
            if(!"0".equals(rewardList.get(2))) {
                respMsg.setReward(rewardList.get(2));
            }
            respMsg.setSuccess(true);
        } else {
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        GreatTradeMgr.completeRandomEvent(player, userData, userData.getTradeStatus());
        userData.getTradeStatus().setRandomEventId(0);
        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);

        //日志
        AutoLogMgr.add(new LogGreatTradeEvent(player.getUserId(), config.getActivityId(), 0, randomEventId, select,
                respMsg.getReward(), consume, getUserAttrValue(userData.getTradeStatus()), userData.getTradeStatus().getAge(), userData.getTotalTradeTimes()));

        if(!StringUtils.isNullOrEmpty(respMsg.getReward())) {
            Property property = PropertyHelper.parseStringToProperty(respMsg.getReward());
            if(property.getCountByGoodsId(eGreatTradeAttrs.Sliver.getId()).compareTo(BigInteger.ZERO) > 0) {
                //事件收益日志
                addEventSliverProfit(respMsg.getReward(), consume, userData.getTradeStatus());
            }else if(property.getCountByGoodsId(eGreatTradeAttrs.Prestige.getId()).compareTo(BigInteger.ZERO) > 0){
                calPrestige(userData.getTradeStatus(), config, true);
            }
        }

        Property reward = checkTitleInfoChange(userData.getTradeStatus().getTitle(), userData.getTradeStatus(), config);
        if(reward != null) {
            changeTradeResource(userData.getTradeStatus(), reward, config);
            addTitleChangeMilepostRecord(userData, userData.getTradeStatus().getTitle(), 5, 0, eventInfo.getId());
            syncTitleChange(userData.getTradeStatus(), PropertyHelper.parsePropertyToString(reward));
            calPrestige(userData.getTradeStatus(), config, true);
            checkSkillUnlock("4", "" + userData.getTradeStatus().getTitle(), "1", config);
        }

        userData.setUpdateOption();
        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_HANDLE_RANDOM_EVENT, respMsg.setRet(0));

        return 0;
    }

    private void addEventSliverProfit(String reward, String consume, GreatTradeSimpleStatus status) {
        BigInteger profit = BigInteger.ZERO;
        if(!StringUtils.isNullOrEmpty(reward)){
            Property rewardProperty = PropertyHelper.parseStringToProperty(reward);
            BigInteger sliver = rewardProperty.getCountByGoodsId(eGreatTradeAttrs.Sliver.getId());
            profit = profit.add(sliver);
        }
        if(!StringUtils.isNullOrEmpty(consume)){
            Property rewardProperty = PropertyHelper.parseStringToProperty(consume);
            BigInteger sliver = rewardProperty.getCountByGoodsId(eGreatTradeAttrs.Sliver.getId());
            if(sliver.compareTo(BigInteger.ZERO) > 0){
                profit = profit.subtract(sliver);
            }else {
                profit = profit.add(sliver);
            }
        }
        BigInteger eventProfit = new BigInteger(status.getEventProfit());
        status.setEventProfit(eventProfit.add(profit).toString());
    }

    private String getUserAttrValue(GreatTradeSimpleStatus status) {
        Property attribute = new Property();
        for (eGreatTradeAttrs value : eGreatTradeAttrs.values()) {
            if(value == eGreatTradeAttrs.Sliver){
                attribute.addProperty(value.getId(), new BigInteger(status.getSilver()));
            }else if(value == eGreatTradeAttrs.Prestige){
                attribute.addProperty(value.getId(), BigInteger.valueOf(status.getPrestige()));
            }else if(value == eGreatTradeAttrs.Health){
                attribute.addProperty(value.getId(), BigInteger.valueOf(status.getHealth()));
            }else if(value == eGreatTradeAttrs.Age){
                attribute.addProperty(value.getId(), BigInteger.valueOf(status.getAge()));
            }else if(value == eGreatTradeAttrs.Assets){
                attribute.addProperty(value.getId(), new BigInteger(status.getAssets()));
            }else if(value == eGreatTradeAttrs.BagCap){
                attribute.addProperty(value.getId(), BigInteger.valueOf(status.getBagCap()));
            }else if(value == eGreatTradeAttrs.OutTimes){
                attribute.addProperty(value.getId(), BigInteger.valueOf(status.getOutTimes()));
            }
        }
        return PropertyHelper.parsePropertyToString(attribute);
    }

    /**
     * 购买盐场
     */
    public int buySaltWorks(int id) {

        int ret = checkOpen();
        if (ret != 0) return ret;

//        if(userData.getTradeStatus().isIll()){
//            return GameErrorCode.E_GREAT_TRADE_CURR_YEAR_ILL;
//        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        if(!isUnLockTypeByTitle(config, 4)){
            return GameErrorCode.E_GREAT_TRADE_SALE_WORKS_LOCK;
        }

        int count = getOwnSaltWorks(userData);
        if(count >= config.getBuySaltWorksLimit(userData.getTradeStatus().getPrestige())){
            return GameErrorCode.E_GREAT_TRADE_SALT_WORKS_NUM_LIMIT;
        }

        GreatTradeGoodsInfo goodsInfo = config.getGreatTradeGoodsInfo(id);
        if(goodsInfo == null){
            return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
        }

        int buyTimes = 0;
        GreatTradeSaltWorks saltWorks;
        if(userData.getSaltWorksMap().containsKey(id)){
            saltWorks = userData.getSaltWorksMap().get(id);
            buyTimes = saltWorks.getTimes();
            if(GreatTradeMgr.getSaltWorksReserves(userData, saltWorks, config) == 0){
                return GameErrorCode.E_GREAT_TRADE_SALE_WORKS_IS_EMPTY;
            }
        }

        BigInteger buyPrice = new BigDecimal(goodsInfo.getBasePrice()).multiply(BigDecimal.valueOf(1000L + buyTimes * config.getSaltBuyParam().get(1))).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).toBigInteger();

        BigInteger silver = new BigInteger(userData.getTradeStatus().getSilver());
        if(silver.compareTo(buyPrice) < 0){
            return GameErrorCode.E_GREAT_TRADE_SLIVER_NO_ENOUGH;
        }

        if(userData.getSaltWorksMap().containsKey(id)){
            saltWorks = userData.getSaltWorksMap().get(id);
            if(saltWorks.getSealOrSell() == 1){
                return GameErrorCode.E_GREAT_TRADE_SALE_WORKS_SEAL;
            }
            //不是出售状态也不让买
            if(saltWorks.getSealOrSell() != 3){
                return GameErrorCode.E_GREAT_TRADE_SALE_WORKS_SEAL;
            }
            saltWorks.setSealOrSell(0);
        }else {
            saltWorks = new GreatTradeSaltWorks();
            saltWorks.setId(id);
            saltWorks.setTimes(1);
            saltWorks.setReserves(100);
            userData.getSaltWorksMap().put(id, saltWorks);
        }
        saltWorks.setTimes(1 + buyTimes);
        //价格上浮
        saltWorks.setPrice(buyPrice.toString());

        userData.getTradeStatus().setSilver(silver.subtract(buyPrice).toString());
        userData.getTradeStatus().addSaltWorks(id);
        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);

        //进程
        List<Integer> paramList = new ArrayList<>();
        paramList.add(saltWorks.getId());
        addMilepostRecord(6, userData.getTradeStatus().getAge(), paramList);
        userData.setUpdateOption();

        //单局承包n座盐场
        player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(BigInteger.valueOf(userData.getTradeStatus().getSaltWorks().size()), 6));

        GreatTradeProto.GreatTradeSaltWorksBuyRespMsg.Builder respMsg = GreatTradeProto.GreatTradeSaltWorksBuyRespMsg.newBuilder();
        respMsg.setRet(ret);
        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_SALT_WORKS_BUY, respMsg);

        return 0;
    }

    private int getOwnSaltWorks(UserGreatTradeData userData) {
        int count = 0;
        for (Map.Entry<Integer, GreatTradeSaltWorks> worksEntry : userData.getSaltWorksMap().entrySet()) {
            GreatTradeSaltWorks saltWorks = worksEntry.getValue();
            if(saltWorks.getSealOrSell() != 3){
                count++;
            }
        }
        return count;
    }

    /**
     * 出售盐场
     */
    public int soldSaltWorks(int id) {

        int ret = checkOpen();
        if (ret != 0) return ret;

//        if(userData.getTradeStatus().isIll()){
//            return GameErrorCode.E_GREAT_TRADE_CURR_YEAR_ILL;
//        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        if(!isUnLockTypeByTitle(config, 4)){
            return GameErrorCode.E_GREAT_TRADE_SALE_WORKS_LOCK;
        }

        GreatTradeGoodsInfo goodsInfo = config.getGreatTradeGoodsInfo(id);
        if(goodsInfo == null){
            return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
        }

        if(!userData.getSaltWorksMap().containsKey(id)){
            return GameErrorCode.E_GREAT_TRADE_CAN_NOT_SOLD_SALE_WORKS;
        }

        GreatTradeSaltWorks saltWorks = userData.getSaltWorksMap().get(id);

        if(GreatTradeMgr.getSaltWorksReserves(userData, saltWorks, config) == 0){
            return GameErrorCode.E_GREAT_TRADE_SALE_WORKS_IS_EMPTY;
        }
        if(saltWorks.getSealOrSell() == 1){
            return GameErrorCode.E_GREAT_TRADE_SALE_WORKS_SEAL;
        }
        if(saltWorks.getSealOrSell() == 3){
            return GameErrorCode.E_GREAT_TRADE_CAN_NOT_SOLD_SALE_WORKS;
        }

        BigInteger soldPrice = GreatTradeMgr.getSaltWorksSellPrice(config, saltWorks);
        saltWorks.setSealOrSell(3);
        userData.getTradeStatus().setSilver(soldPrice.add(new BigInteger(userData.getTradeStatus().getSilver())).toString());

        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);
        userData.setUpdateOption();

        GreatTradeProto.GreatTradeSaltWorksSoldRespMsg.Builder respMsg = GreatTradeProto.GreatTradeSaltWorksSoldRespMsg.newBuilder();
        respMsg.setRet(ret);
        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_SALT_WORKS_SOLD, respMsg);
        return 0;
    }

    /**
     * 开采盐场
     */
    public int exploitSaltWorks(int id, int type) {

        int ret = checkOpen();
        if (ret != 0) return ret;

//        if(userData.getTradeStatus().isIllt()){
//            return GameErrorCode.E_GREAT_TRADE_CURR_YEAR_ILL;
//        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        if(!isUnLockTypeByTitle(config, 4)){
            return GameErrorCode.E_GREAT_TRADE_SALE_WORKS_LOCK;
        }

        GreatTradeGoodsInfo goodsInfo = config.getGreatTradeGoodsInfo(id);
        if(goodsInfo == null){
            return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
        }

        GreatTradeSaltWorks saltWorks = userData.getSaltWorksMap().get(id);
        if(saltWorks == null){
            return GameErrorCode.E_GREAT_TRADE_CAN_NOT_SOLD_SALE_WORKS;
        }

        if(type >= config.getSaltMineRiskSpeed().size() || type < 0){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        if(saltWorks.getSealOrSell() == 1){
            return GameErrorCode.E_GREAT_TRADE_SALE_WORKS_SEAL;
        }
        if(saltWorks.getSealOrSell() == 2){
            return GameErrorCode.E_GREAT_TRADE_CAN_NOT_SOLD_SALE_WORKS;
        }

        saltWorks.setMiningSpeed(type);
        userData.setUpdateOption();

        GreatTradeProto.GreatTradeSaltWorksExploitRespMsg.Builder respMsg = GreatTradeProto.GreatTradeSaltWorksExploitRespMsg.newBuilder().setRet(0);
        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_SALT_WORKS_EXPLOIT, respMsg);

        return 0;
    }

    /**
     * 结算商途
     * @param normal 是否正常结算
     */
    private int closeTrade(boolean normal, GreatTradeConfig config) {


        userData.getTradeStatus().setTradeFinish(true);

        //单局资产冲榜
        BigInteger assets = GreatTradeMgr.toPositive(new BigInteger(userData.getTradeStatus().getAssets()));
        player.notifyListener(eGamePlayerEventType.GreatTradeAssetCrossRank.getValue(), assets);
        //单局名望冲榜
        //player.notifyListener(eGamePlayerEventType.GreatTradePrestigeCrossRank.getValue(), BigInteger.valueOf(userData.getTradeStatus().getPrestige()));

        player.notifyListener(eGamePlayerEventType.GreatTradeSliverToken.getValue(), assets);
        player.notifyListener(eGamePlayerEventType.GreatTradeBronzeToken.getValue(), assets);
        player.notifyListener(eGamePlayerEventType.GreatTradeGoldToken.getValue(), assets);

        //最高称号、资产
        if(userData.getTradeStatus().getTitle() > userData.getMaxTitle()){
            userData.setMaxTitle(userData.getTradeStatus().getTitle());
        }

        //单局最终最高
        if(assets.compareTo(new BigInteger(userData.getMaxAssets())) > 0){
            userData.setMaxAssets(assets.toString());
        }

        addMilepostRecord(7, userData.getTradeStatus().getAge(), new ArrayList<>());
        List<String> paramList = new ArrayList<>();
        paramList.add(userData.getTradeStatus().getAssets());
        paramList.add(userData.getTradeStatus().getPrestige() + "");
        GreatTradeMilepostRecord record = new GreatTradeMilepostRecord(8, userData.getTradeStatus().getAge(), StringUtils.listToString(paramList, "|"));
        userData.getMilepostRecordList().add(record);

        //财神
        int goods = 0;
        BigInteger sellMax = BigInteger.ZERO;
        for (Map.Entry<Integer, String> entry : userData.getTradeStatus().getSellMoney().entrySet()) {
            BigInteger val = new BigInteger(entry.getValue());
            if(val.compareTo(sellMax) > 0){
                sellMax = val;
                goods = entry.getKey();
            }
        }
        if(goods > 0){
            List<Integer> paramList2 = new ArrayList<>();
            paramList2.add(goods);
            paramList2.add(GreatTradeMgr.getMaxOutArea(userData));
            addMilepostRecord(9, userData.getTradeStatus().getAge(), paramList2);
        }


        if(normal) {

            checkSkillUnlock("10", "0", "" + userData.getTradeStatus().getAge(), config);

            userData.setCompleteTimes(1 + userData.getCompleteTimes());
            //美女同游 成就
            checkSkillUnlock("1", "0", "" + userData.getCompleteTimes(), config);

            //完成大商途{0}次
            player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(BigInteger.valueOf(userData.getCompleteTimes()), 5));

        }

        //单局最终资产与单局最高资产相差{0}倍数
        BigInteger maxAsserts = GreatTradeMgr.toPositive(new BigInteger(userData.getTradeStatus().getMaxAssets()));
        if(maxAsserts.compareTo(BigInteger.ZERO) > 0 && assets.compareTo(BigInteger.ZERO) > 0){
            int beiShu = new BigDecimal(maxAsserts).divide(new BigDecimal(assets), 0, BigDecimal.ROUND_DOWN).intValue();
            player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(BigInteger.ONE, 10, 0, beiShu));
        }

        //日志
        GreatTradeSimpleStatus simpleStatus = userData.getTradeStatus();
        AutoLogMgr.add(new LogGreatTradeEnd(player.getUserId(), config.getActivityId(), simpleStatus.getTitle(), simpleStatus.getAge(), simpleStatus.getAssets(), simpleStatus.getMaxAssets(),
                simpleStatus.getPrestige(), simpleStatus.getBirth(), simpleStatus.isUseGoods(), !normal, userData.getTotalTradeTimes(),
                simpleStatus.getGoodsProfit(), simpleStatus.getIndustryProfit(), simpleStatus.getEventProfit(), simpleStatus.getSaltWorksProfit()));

        return 0;
    }

    /**
     * 提前结算
     */
    public int endTrade() {

        int ret = checkOpen();
        if (ret != 0) return ret;

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);

        closeTrade(false, config);

        GreatTradeProto.CloseGreatTradeRespMsg.Builder respMsg = GreatTradeProto.CloseGreatTradeRespMsg.newBuilder().setRet(0);
        GreatTradeTitleInfo titleInfo = config.getTitleInfoByAssets(userData.getTradeStatus().getAssets());
        if(titleInfo != null){
            player.getModule(CurrencyModule.class).addCurrency(titleInfo.getEndReward(), eLogMoneyType.GreatTradeActivity, eLogMoneyType.GreatTradeActivityEndTradeReward);
            respMsg.setReward(titleInfo.getEndReward());
        }
        userData.setUpdateOption();

        for (GreatTradeMilepostRecord milepostRecord : userData.getMilepostRecordList()) {
            respMsg.addMilepost(GreatTradeActivityPb.buildMilepost(milepostRecord));
        }

        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_CLOSE, respMsg);
        return 0;
    }

    /**
     * 检查美女技能解锁
     */
    public void checkSkillUnlock(String param1, String param3, String param4, GreatTradeConfig config){
        for (GreatTradeUnlockSkillInfo unlockSkillInfo : config.getUnlockSkillInfoList()) {
            if(!param1.equals(unlockSkillInfo.getParams().get(0)) || (!param3.equals(unlockSkillInfo.getParams().get(2)) && !param1.equals("4"))){
                continue;
            }
            BigInteger val = new BigInteger(param4);
            BigInteger param4Val = new BigInteger(unlockSkillInfo.getParams().get(3));
            if(param1.equals("10")){//年龄大于
                if (val.compareTo(param4Val) > 0) {
                    unlockSkill(Integer.valueOf(unlockSkillInfo.getParams().get(1)), config);
                }
            } else if(param1.equals("4")){
                BigInteger val2 = new BigInteger(param3);
                BigInteger param3Val = new BigInteger(unlockSkillInfo.getParams().get(2));
                if(val2.compareTo(param3Val) >= 0 && val.compareTo(param4Val) >= 0){
                    unlockSkill(Integer.valueOf(unlockSkillInfo.getParams().get(1)), config);
                }
            }else {
                if (val.compareTo(param4Val) >= 0) {
                    unlockSkill(Integer.valueOf(unlockSkillInfo.getParams().get(1)), config);
                }
            }
        }
    }

    private void checkHealthValid(GreatTradeSimpleStatus tradeStatus, int min, Map<Integer, GreatTradeBeautySkill> beautyMap, GreatTradeConfig config) {
        if(tradeStatus.getHealth() <= min){
            tradeStatus.setHealth(min);
            tradeStatus.setStatus(2);
            tradeStatus.setIll(true);
            return;
        }
        int maxHealth = GreatTradeMgr.getUserMaxHealth(beautyMap, config, tradeStatus.getExMaxHealth());
        if(tradeStatus.getHealth() > maxHealth){
            tradeStatus.setHealth(maxHealth);
        }
    }

    private void buildYearProfit(UserGreatTradeData userData, GreatTradeProto.GreatTradeNextYearRespMsg.Builder respMsg) {
        for (int i = 0; i < userData.getProfitMap().size(); i++) {
            Map<Integer, String> map = userData.getProfitMap().get(i);
            GreatTradeProto.GreatTradeYearProfitTemp.Builder builder = GreatTradeProto.GreatTradeYearProfitTemp.newBuilder();
            for (Map.Entry<Integer, String> entry : map.entrySet()) {
                GreatTradeProto.GreatTradeYearProfitItemTemp.Builder itemBuild = GreatTradeProto.GreatTradeYearProfitItemTemp.newBuilder();
                itemBuild.setNpcId(entry.getKey());
                itemBuild.setValue(entry.getValue());
                itemBuild.setType(entry.getKey());
                builder.addItem(itemBuild);
            }

            respMsg.addProfit(builder);
        }
    }

    private Map<Integer, String> addYearProfitRecord(IndustryResult industryResult, List<SaltWorksResult> saltWorksResults, int addSkillHealth, BigInteger addSkillSliver) {
        Map<Integer, String> map = new HashMap<>();
        if(industryResult.getIndustryProfit().compareTo(BigInteger.ZERO) > 0){
            map.put(userData.getIndustry().getId(), industryResult.getIndustryProfit().toString());
        }
        for (SaltWorksResult worksResult : saltWorksResults) {
            if(worksResult.getAddSliver().compareTo(BigInteger.ZERO) > 0 && worksResult.getRet() != 3 && worksResult.getRet() != 1){
                map.put(worksResult.getId(), worksResult.getAddSliver().toString());
            }
        }
        if(addSkillHealth > 0){
            map.put(3, addSkillHealth + "");
        }
        if(addSkillSliver.compareTo(BigInteger.ZERO) > 0){
            map.put(10, addSkillSliver.toString());
        }
        GreatTradeMgr.addThisYearProfit(userData, map);
        return map;
    }

    private HealthResult calYearHealthEvent(GreatTradeSimpleStatus tempStatus, GreatTradeConfig config, Random random, boolean shouChen) {
        //随机事件
        int randomEventId = 0;
        //健康事件
        int subHealth = 0;
        //技能增加
        int skillAddition = 0;

        if(!tempStatus.isIll()) {

            //健康事件
            BigDecimal asserts = new BigDecimal(tempStatus.getAssets());
            BigDecimal lastYear = new BigDecimal(tempStatus.getLastAssets());
            if(asserts.compareTo(BigDecimal.ZERO) > 0 && lastYear.compareTo(BigDecimal.ZERO) > 0){
                if (asserts.compareTo(lastYear.multiply(BigDecimal.valueOf(1000 + config.getEventHealthyMoneyTomuch().get(0)))
                        .divide(BigDecimal.valueOf(1000), 3, BigDecimal.ROUND_DOWN)) >= 0) {
                    if (random.nextInt(1000) < config.getEventHealthyMoneyTomuch().get(1)) {
                        subHealth = config.getEventHealthyMoneyTomuch().get(2);
                    }
                }
            }

            //int illWeight = GreatTradeMgr.getIllWeight(tempStatus.getHealth(), config);
            //没有触发健康事件，可触发生病事件
            //int randomWeigh = random.nextInt(1000);
            if (subHealth == 0 && !shouChen && tempStatus.getHealth() == 0) {
                //患病
                tempStatus.setIll(true);
                tempStatus.setStatus(2);
            }else {
                randomEventId = GreatTradeMgr.calYearRandomEvent(tempStatus, config, random);
            }


            //健康自然流失
            int lose = 0;
            if (config.getHealthyLoseYear().get(0) == 1 || (tempStatus.getCurYear() > 1 && tempStatus.getCurYear() % (config.getHealthyLoseYear().get(0)) == 0)) {
                lose = config.getHealthyLoseYear().get(1);
            }
            int yearChange = config.getHealthChangeByAge(tempStatus.getAge());

            //技能恢复
            skillAddition = GreatTradeMgr.getSkillAddition(3, userData.getBeautyMap(), null, null, config);

            tempStatus.setHealth(tempStatus.getHealth() - subHealth + skillAddition - lose + yearChange);
            checkHealthValid(tempStatus, 0, userData.getBeautyMap(), config);

        }

        return new HealthResult(randomEventId, subHealth, skillAddition);
    }

    /**
     * 解锁技能
     */
    public void unlockBeautySkill(int skillId) {

        if(userData == null){
            return;
        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();
        if(config == null){
            return;
        }
        if(!ActivityMgr.activityInShowTime(config.getActivityInfo())){
            return;
        }

        unlockSkill(skillId, config);
        userData.setUpdateOption();

        //美女解锁成就
        int size = userData.getBeautyMap().size();
        player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(BigInteger.valueOf(size), 1));

        syncUserData();
    }

    private void unlockSkill(int skillId, GreatTradeConfig config) {
        int logType = 0;//解锁
        GreatTradeBeautySkill skill = userData.getBeautyMap().get(skillId);
        if(skill == null){
            skill = new GreatTradeBeautySkill();
            skill.setId(skillId);
            skill.setLv(1);
            userData.getBeautyMap().put(skillId, skill);
            checkSkillUnlock("3", "0", "" + userData.getBeautyMap().size(), config);
        }else {
            logType = 1;//美名升级
        }
        int oldLv = skill.getTotalLv();
        GreatTradeSkillsInfo skillsInfo = config.getGreatTradeSkillsInfo(skillId);
        if(skillsInfo != null){
            int max = config.getMaxGreatTradeSkillLv(skillId);
            UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(skillsInfo.getBeauty());
            if(userBeauty != null){
                //int addLv = getAddLv(userBeauty.getIdentityLv(), config);
                //又改成不要美名加成
                int addLv = 0;
                if(addLv + skill.getLv() > max){
                    skill.setAddLv(max - skill.getLv());
                }else {
                    skill.setAddLv(addLv);
                }
            }
        }

        if(logType == 0){
            //解锁日志
            AutoLogMgr.add(new LogGreatTradeSkillUnlock(player.getUserId(), config.getActivityId(), skillId, skill.getTotalLv(), userData.getTotalTradeTimes()));
        }else {
            if(skill.getTotalLv() > oldLv){
                //美名升级日志
                AutoLogMgr.add(new LogGreatTradeSkillUpgrade(player.getUserId(), config.getActivityId(), skillId, oldLv, skill.getTotalLv(), 1, "", userData.getTotalTradeTimes()));
            }
        }

        //美女解锁成就
        int size = userData.getBeautyMap().size();
        player.notifyListener(eGamePlayerEventType.GreatTradeMerchant.getValue(), new ValueFourParamArgs(BigInteger.valueOf(size), 1));
    }

    /**
     * 美女技能升级
     */
    public int upgradeBeautySkill(int beautySkillId) {

        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        if(!userData.getBeautyMap().containsKey(beautySkillId)){
            return GameErrorCode.E_GREAT_TRADE_SKILL_LOCK;
        }

        GreatTradeBeautySkill skill = userData.getBeautyMap().get(beautySkillId);
        GreatTradeConfig config = GreatTradeMgr.getConfig();
        GreatTradeSkillsInfo skillsInfo = config.getGreatTradeSkillsInfo(beautySkillId, skill.getTotalLv());
        if(skillsInfo == null){
            return GameErrorCode.E_GREAT_TRADE_CONFIG_NO_FIND;
        }
        if(skillsInfo.getCost() == 0){
            return GameErrorCode.E_GREAT_TRADE_SKILL_LEVEL_MAX;
        }

        String cost = config.getBeautySkillUpgradeItemId() + "=" + skillsInfo.getCost();
        if(!player.getModule(CurrencyModule.class).removeCurrency(PropertyHelper.parseStringToProperty(cost), eLogMoneyType.GreatTradeActivity, eLogMoneyType.GreatTradeActivitySkillUpGradeConsume)){
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        int oldLv = skill.getTotalLv();
        skill.setLv(1 + skill.getLv());
        userData.setUpdateOption();

        //继承点消耗成就
        player.notifyListener(eGamePlayerEventType.GreatTradeFate.getValue(), new ValueFourParamArgs(BigInteger.valueOf(skillsInfo.getCost()), 0));

        //美名升级日志
        AutoLogMgr.add(new LogGreatTradeSkillUpgrade(player.getUserId(), config.getActivityId(), beautySkillId, oldLv, skill.getTotalLv(), 2, cost, userData.getTotalTradeTimes()));

        GreatTradeProto.GreatTradeBeautyUpgradeRespMsg.Builder respMsg = GreatTradeProto.GreatTradeBeautyUpgradeRespMsg.newBuilder().setRet(0);
        respMsg.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_BEAUTY_UPGRADE, respMsg);
        return 0;
    }

    private boolean isEnough(GreatTradeSimpleStatus tradeStatus, Property property){
        if(property.getCountByGoodsId(eGreatTradeAttrs.Sliver.getId()).compareTo(BigInteger.ZERO) > 0){
            return new BigInteger(tradeStatus.getSilver()).compareTo(property.getCountByGoodsId(eGreatTradeAttrs.Sliver.getId())) >= 0;
        }
        if(property.getCountByGoodsId(eGreatTradeAttrs.Prestige.getId()).compareTo(BigInteger.ZERO) > 0){
            return tradeStatus.getPrestige() >= property.getCountByGoodsId(eGreatTradeAttrs.Prestige.getId()).longValue();
        }
        if(property.getCountByGoodsId(eGreatTradeAttrs.Health.getId()).compareTo(BigInteger.ZERO) > 0){
            return tradeStatus.getHealth() >= property.getCountByGoodsId(eGreatTradeAttrs.Health.getId()).longValue();
        }
        if(property.getCountByGoodsId(eGreatTradeAttrs.Assets.getId()).compareTo(BigInteger.ZERO) > 0){
            return new BigInteger(tradeStatus.getAssets()).compareTo(property.getCountByGoodsId(eGreatTradeAttrs.Assets.getId())) >= 0;
        }
        return false;
    }

    private void consumeTradeResource(GreatTradeSimpleStatus tradeStatus, Property property, GreatTradeConfig config) {
        BigInteger count = property.getCountByGoodsId(eGreatTradeAttrs.Sliver.getId());
        if(count.compareTo(BigInteger.ZERO) > 0){
            tradeStatus.setSilver(new BigInteger(tradeStatus.getSilver()).subtract(count).toString());
        }
        count = property.getCountByGoodsId(eGreatTradeAttrs.Prestige.getId());
        if(count.compareTo(BigInteger.ZERO) > 0){
            tradeStatus.setPrestige(tradeStatus.getPrestige() - count.longValue());
        }
        count = property.getCountByGoodsId(eGreatTradeAttrs.Health.getId());
        if(count.compareTo(BigInteger.ZERO) > 0){
            tradeStatus.setHealth(tradeStatus.getHealth() - count.intValue());
            checkHealthValid(userData.getTradeStatus(), 0, userData.getBeautyMap(), config);
        }
    }

    private void changeTradeResource(GreatTradeSimpleStatus tradeStatus, Property property, GreatTradeConfig config) {
        BigInteger count = property.getCountByGoodsId(eGreatTradeAttrs.Sliver.getId());
        if(count.compareTo(BigInteger.ZERO) != 0){
            tradeStatus.setSilver(new BigInteger(tradeStatus.getSilver()).add(count).toString());
        }
        count = property.getCountByGoodsId(eGreatTradeAttrs.Prestige.getId());
        if(count.compareTo(BigInteger.ZERO) != 0){
            tradeStatus.setPrestige(tradeStatus.getPrestige() + count.longValue());
        }
        count = property.getCountByGoodsId(eGreatTradeAttrs.Health.getId());
        if(count.compareTo(BigInteger.ZERO) != 0){
            tradeStatus.setHealth(tradeStatus.getHealth() + count.intValue());
            checkHealthValid(tradeStatus, 0, userData.getBeautyMap(), config);
        }
        count = property.getCountByGoodsId(eGreatTradeAttrs.BagCap.getId());
        if(count.compareTo(BigInteger.ZERO) > 0){
            tradeStatus.setBagCap(tradeStatus.getBagCap() + count.intValue());
        }
        count = property.getCountByGoodsId(eGreatTradeAttrs.OutTimes.getId());
        if(count.compareTo(BigInteger.ZERO) > 0){
            if(isUnLockTypeByTitle(config, 2)){
                //事件额外的 可以超上限
                tradeStatus.setOutTimes(count.intValue() + tradeStatus.getOutTimes());
            }
        }

        //是否是行商物品
        for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
            int id = entry.getKey();
            GreatTradeGoodsInfo goodsInfo = config.getGreatTradeGoodsInfo(id);
            if(goodsInfo != null && goodsInfo.getType() == 1){
                int num = entry.getValue().intValue();
                long price = Long.valueOf(goodsInfo.getBasePrice());
                //商品价格取基础价格或者市场价格
                Map<Integer, Integer> priceMap = userData.getGoodsPriceList();
                if(priceMap.containsKey(id)){
                    price = priceMap.get(id);
                }
                //直接进背包
                addBagGoods(id, num, BigInteger.valueOf(price).multiply(BigInteger.valueOf(num)));
            }
        }
    }

    public boolean resetOneDay(){

        if(userData == null){
            return false;
        }

        // 没有活动
        if (!ActivityMgr.activityInTime(GreatTradeMgr.getActivityInfo()) || GreatTradeMgr.getConfig() == null) {
            return false;
        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        int zeroTime = DateHelper.getTodayZeroTime();
        if(userData.getDayResetTime() != zeroTime){
            userData.setDayFreeTimes(config.getFreeNum());
            userData.setDayResetTime(zeroTime);
            syncUserData();
            return true;
        }
        return false;
    }

    /**
     * 购买商贴
     */
    public void rechargeCard(int activityId, MallInfo mallInfo) {
        try {
            if (userData == null) {
                return;
            }
            if (userData.getActivityId() != activityId) {
                return;
            }

            GreatTradeConfig config = GreatTradeMgr.getConfig();
            if (config == null) {
                return;
            }

            BigInteger assets = BigInteger.ZERO;
            if(!StringUtils.isNullOrEmpty(userData.getMaxAssets())){
                assets = new BigInteger(userData.getMaxAssets());
            }
            if(mallInfo.getShopType() == eShopType.ChineseChessSilverToken.getValue()){
                userData.setBuySliverToken(1);
                player.notifyListener(eGamePlayerEventType.GreatTradeSliverToken.getValue(), assets);
            }else if(mallInfo.getShopType() == eShopType.ChineseChessGoldToken.getValue()){
                userData.setBuyGoldToken(1);
                player.notifyListener(eGamePlayerEventType.GreatTradeGoldToken.getValue(), assets);
            }

            //解锁技能
            Property property = PropertyHelper.parseStringToProperty(mallInfo.getReward());
            if (property.getCountByGoodsId(eItemId.GREAT_TRADE_SKILL_ITEM.getValue()).compareTo(BigInteger.ZERO) > 0) {
                unlockSkill(property.getCountByGoodsId(eItemId.GREAT_TRADE_SKILL_ITEM.getValue()).intValue(), config);
                userData.setUpdateOption();
            }
            syncUserData();

        }catch (Exception e){
            GreatTradeMgr.getLogger().error(" {} rechargeCard error, mallId {} ,activityId : {}", player.getUserId(), mallInfo.getMallId(), mallInfo.getActivityId());
        }
    }

    /**
     * 美名加成
     */
    public void calBeautySkill(UserBeauty userBeauty) {
        if(userData == null){
            return;
        }

        GreatTradeConfig config = GreatTradeMgr.getConfig();

        if(config == null){
            return;
        }

        List<Integer> skillList = config.getSkillListByBeautyId(userBeauty.getBeautyId());
        //int addLv = getAddLv(userBeauty.getIdentityLv(), config);
        int addLv = 0;
        for (int skill : skillList) {
            GreatTradeBeautySkill beautySkill = userData.getBeautyMap().get(skill);
            if(beautySkill != null){
                int max = config.getMaxGreatTradeSkillLv(beautySkill.getId());
                if(addLv + beautySkill.getLv() > max){
                    beautySkill.setAddLv(max - beautySkill.getLv());
                }else {
                    beautySkill.setAddLv(addLv);
                }
            }
        }
        userData.setUpdateOption();
        syncUserData();
    }

    private int getAddLv(int identityLv, GreatTradeConfig config) {
        int addLv;
        if(config.getBeautyExLvList().size() < identityLv){
            addLv = config.getBeautyExLvList().get(config.getBeautyExLvList().size() - 1);
        }else {
            addLv = config.getBeautyExLvList().get(identityLv - 1);
        }
        return addLv;
    }

    public boolean canPrecharge(MallInfo mallInfo) {
        if(userData == null){
            return false;
        }
        // 没有活动
        if (!ActivityMgr.activityInShowTime(GreatTradeMgr.getActivityInfo()) || GreatTradeMgr.getConfig() == null) {
            return false;
        }

        return !player.getModule(ActivityMallModule.class).isOverLimitBuyCount(mallInfo, 1);
    }

    /**
     * 购买背包格子
     */
    public int buyBagCap() {
        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        GreatTradeConfig config = GreatTradeMgr.getConfig();

        if(config == null){
            return GameErrorCode.E_ACTIVITY_NO_FOUND;
        }

        int times = userData.getTradeStatus().getBuyBayCapTimes();
        long cost;
        List<Long> costList = config.getBagCellCostList();
        if(costList.size() == 0){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        if(times > costList.size() - 1){
            //cost = costList.get(costList.size() - 1);
            return GameErrorCode.E_GREAT_TRADE_BAG_BUG_LIMIT;
        }else {
            cost = costList.get(times);
        }
        int num;
        List<Integer> numList = config.getBagCellBuyNumList();
        if(times > numList.size() - 1){
            num = numList.get(numList.size() - 1);
        }else {
            num = numList.get(times);
        }
        if(cost == 0 || num == 0){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        Property consume = PropertyHelper.parseStringToProperty(eGreatTradeAttrs.Sliver.getId() + "=" + cost);
        if(!isEnough(userData.getTradeStatus(), consume)){
            return GameErrorCode.E_GREAT_TRADE_SLIVER_NO_ENOUGH;
        }

        consumeTradeResource(userData.getTradeStatus(), consume, config);
        userData.getTradeStatus().setBagCap(num + userData.getTradeStatus().getBagCap());
        userData.getTradeStatus().setBuyBayCapTimes(1 + userData.getTradeStatus().getBuyBayCapTimes());
        GreatTradeMgr.calUserAssert(userData, userData.getTradeStatus(), config);
        userData.setUpdateOption();

        GreatTradeProto.GreatTradeBuyBagCapRespMsg.Builder builder = GreatTradeProto.GreatTradeBuyBagCapRespMsg.newBuilder().setRet(0);
        builder.setUserData(GreatTradeActivityPb.buildUserTemp(userData, config));
        player.sendPacket(Protocol.U_GREAT_TRADE_BUY_BAG_CAP, builder);
        return 0;
    }

    public boolean isBuyToken(int shopType) {
        if(userData == null){
            return false;
        }
        if(shopType == eShopType.ChineseChessGoldToken.getValue()){
            return userData.getBuyGoldToken() > 0;
        }
        if(shopType == eShopType.ChineseChessSilverToken.getValue()){
            return userData.getBuySliverToken() > 0;
        }
        return false;
    }
}
